Module 01: Introduction to Shiny
School of Mathematical and Physical Sciences
2024-09-28
Introducing Shiny
Shiny is a framework for creating web applications using R code.comfortable with the basics of R, such as writing functions, indexing vectors and lists, debugging simple errors, and working with data structures like data frames
interested in creating interactive web applications, and
have no or minimal experience with Shiny for R.
If you have a bit of experience, you’ll see things in a new way. If you don’t, we’ll get you started on the right footing.
Server
+
⇄
Client / Browser
+ +
User Interface (UI)
fluidPage() creates the most basic layout
Tabsets
tabsetPanel()
Navbars and navlists
See navlistPanel()
and navbarPage()
Dashboards
titlePanel() and sidebarLayout() create a basic Shiny app/layout with a sidebar
sidebarLayout() takes two functions
sidebarPanel(): Includes content displayed in the sidebarmainPanel(): Includes content displayed in the main panelfluidRow() and column(): Divide UI into rows/columnsui <- fluidPage(
titlePanel("This is the title panel"),
sidebarLayout(
sidebarPanel("Title: Sidebar panel"),
mainPanel(
"Title: Main panel",
fluidRow(
column(width = 4, "Column 1: Description here"),
column(width = 4, "Column 2: Model summary"),
column(
width = 3,
offset = 1,
"Column 3: Model visualization"
)
)
)
)
)
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)tabsetPanel() + tabPanel()
ui <- fluidPage(
titlePanel("This is the title panel"),
sidebarLayout(
sidebarPanel("This is the sidebar panel"),
mainPanel(
tabsetPanel(
type = "tabs",
tabPanel(
"3d Frequency Plot",
"Tab 1: plot here"
),
tabPanel(
"Histogram",
"Tab 2: another plot here"
),
tabPanel(
"Model Summary",
h4("Tab 3: estimation results here")
),
tabPanel(
"Data Summary",
h4("Tab 4: Variable summaries")
)
)
)
)
)
server <- function(input, output, session) {}
shinyApp(ui = ui, server = server)Input Widgets
textInput(inputId = "username", label = "Enter your username", value = "Write here")
inputId connects front end with back end, e.g., if UI has input with ID name, the server function will access it with input$name
name = simple string (only letters, numbers, and underscores) and unique
label argument: used to create human-readable labelvalue argument: default valueinput$...
inputId and label arguments by position, and all other arguments by namesliderInput("min", "Limit (minimum)", value = 50, min = 0, max = 100)server <- function(input, output, session) {}animals <- c("dog", "cat", "mouse") # Predefining some categories
ui <- fluidPage(
# Free text
textInput("name", "What's your name?"),
textInput(inputId = "username", label = "Enter your username", placeholder = "Write here"),
passwordInput("password", "What's your password?"),
textAreaInput("story", "Tell me about yourself", rows = 3),
# Numeric inputs
numericInput("num", "Number one", value = 0, min = 0, max = 100),
sliderInput("num2", "Number two", value = 50, min = 0, max = 100),
sliderInput("rng", "Range", value = c(10, 20), min = 0, max = 100),
# Dates
dateInput("dob", "When were you born?"),
dateRangeInput("holiday", "When do you want to go on vacation next?"),
# Limited choices
selectInput("state", "What's your favourite animal?", animals),
radioButtons("animal", "What's your favourite animal?", animals),
selectInput("state", "What's your favourite animal?", animals, multiple = TRUE),
checkboxGroupInput("animal2", "What animals do you like?", animals),
# Single checkbox
checkboxInput("cleanup", "Clean up?", value = TRUE),
checkboxInput("shutdown", "Shutdown?"),
# File uploads
fileInput("upload", NULL),
# Action buttons
actionButton("click", "Click me!"),
actionButton("drink", "Drink me!", icon = icon("cocktail"))
)
server <- function(input, output, session) {}
shinyApp(ui, server)Outputs
textOutput("text") as ID text that is filled by the servertext, you’ll access it in the server function with output$text (see below)dataTableOutput() vs DT::DTOutput()
shiny::renderDataTable() is deprecated as of shiny 1.8.1DT::renderDT() insteadWe need some data that we will be able to interact with for our Shiny apps today.
Data are collected from Meteostat’s bulk data API for international airports in the lower 48 states.
# A tibble: 28,594 × 17
id name airport_code country state region longitude latitude date
<dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <date>
1 72202 Miami KMIA US FL South -80.3 25.8 2020-01-01
2 72202 Miami KMIA US FL South -80.3 25.8 2020-01-02
3 72202 Miami KMIA US FL South -80.3 25.8 2020-01-03
4 72202 Miami KMIA US FL South -80.3 25.8 2020-01-04
5 72202 Miami KMIA US FL South -80.3 25.8 2020-01-05
6 72202 Miami KMIA US FL South -80.3 25.8 2020-01-06
7 72202 Miami KMIA US FL South -80.3 25.8 2020-01-07
8 72202 Miami KMIA US FL South -80.3 25.8 2020-01-08
9 72202 Miami KMIA US FL South -80.3 25.8 2020-01-09
10 72202 Miami KMIA US FL South -80.3 25.8 2020-01-10
# ℹ 28,584 more rows
# ℹ 8 more variables: temp_avg <dbl>, temp_min <dbl>, temp_max <dbl>,
# precip <dbl>, snow <dbl>, wind_direction <dbl>, wind_speed <dbl>,
# air_press <dbl>
demos/demo01.R
library(tidyverse)
library(shiny)
d <- readr::read_csv(here::here("data/weather.csv"))
ui <- fluidPage(
titlePanel("Temperatures at Major Airports"),
sidebarLayout(
sidebarPanel(
radioButtons(
"name", "Select an airport",
choices = c(
"Seattle-Tacoma",
"Raleigh-Durham",
"Houston Intercontinental",
"Denver",
"Los Angeles",
"John F. Kennedy"
)
)
),
mainPanel(
plotOutput("plot")
)
)
)
server <- function(input, output, session) {
output$plot <- renderPlot({
d |>
filter(name %in% input$name) |>
ggplot(aes(x = date, y = temp_avg)) +
geom_line() +
theme_minimal()
})
}
shinyApp(ui = ui, server = server)https://github.com/iris-yi-jiang/DataViz_Shiny.git)Open exercises/ex01.R and execute it via the Run App button in RStudio.
Check that you are able successfully run the shiny app and are able to interact with it by picking a new airport.
If everything is working try modifying the code, e.g. try adding or removing a city from radioButtons().
What happens if you add a city that is not in the weather.csv data set to the radio button input?
05:00
Troubleshooting
Do you have the latest versions of shiny and tidyverse installed?
exercises/ex02.R try changing the radioButton() input to something else.What happens if you use an input capable of selecting multiple values, e.g.,
checkboxGroupInput()
or selectInput() with multiple = TRUE
10:00
plotly::ggplotly() is a function that converts a ggplot object into a plotly object.
This allows you to create interactive plots from ggplot objects.
demos/ex02_plotly.R
library(tidyverse)
library(shiny)
d <- readr::read_csv(here::here("data/weather.csv"))
ui <- fluidPage(
titlePanel("Temperatures at Major Airports"),
sidebarLayout(
sidebarPanel(
selectInput(
"name", "Select an airport",
choices = c(
"Seattle-Tacoma",
"Raleigh-Durham",
"Houston Intercontinental",
"Denver",
"Los Angeles",
"John F. Kennedy"
),
selected = "Seattle-Tacoma",
multiple = TRUE
)
),
mainPanel(
plotlyOutput("plot")
)
)
)
server <- function(input, output, session) {
output$plot <- renderPlotly({
p <- d |>
filter(name %in% input$name) |>
ggplot(aes(x = date, y = temp_avg, color = name)) +
geom_line() +
theme_minimal() +
labs(color = "") +
theme(legend.position = "bottom")
plotly::ggplotly(p)
})
}
shinyApp(ui = ui, server = server)